//*******************************************************************************
// COPYRIGHT NOTES
// ---------------
// This is a sample for BCGControlBar Library Professional Edition
// Copyright (C) 1998-2016 BCGSoft Ltd.
// All rights reserved.
//
// This source code can be used, distributed or modified
// only under terms and conditions 
// of the accompanying license agreement.
//*******************************************************************************
//
// ChartSurfaceAdvancedView.cpp : implementation file
//

#include "stdafx.h"
#include "bcgpchartexample.h"
#include "ChartSurfaceAdvancedView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CChartSurfaceAdvancedView

IMPLEMENT_DYNCREATE(CChartSurfaceAdvancedView, CBCGPChartExampleView)

CChartSurfaceAdvancedView::CChartSurfaceAdvancedView()
	: CBCGPChartExampleView(CChartSurfaceAdvancedView::IDD)
{
	//{{AFX_DATA_INIT(CChartSurfaceAdvancedView)
	m_bUseSoftwareRendering = FALSE;
	m_nSurfaceType = 1;
	m_nColorMode = 1;
	m_nColorCount = 1;
	m_bDrawFlat = FALSE;
	m_nFlatLevel = 50;
	m_nFrameStyle = 1;
	m_bColoredFrame = TRUE;
	m_bShowLevelRangeInLegend = TRUE;
	m_bContinuousLegendKey = TRUE;
	m_bShowWalls = TRUE;
	m_bWireFrame = FALSE;
	m_bZoomScroll = FALSE;
	m_bShowFloor = TRUE;
	//}}AFX_DATA_INIT
}

CChartSurfaceAdvancedView::~CChartSurfaceAdvancedView()
{
}

void CChartSurfaceAdvancedView::DoDataExchange(CDataExchange* pDX)
{
	CBCGPChartExampleView::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CChartSurfaceAdvancedView)
	DDX_Control(pDX, IDC_COLORED_FRAME, m_wndColoredFrame);
	DDX_Control(pDX, IDC_WIRE_FRAME, m_wndWireFrame);
	DDX_Control(pDX, IDC_STATIC_FLAT_LEVEL, m_wndFlatLevelLabel);
	DDX_Control(pDX, IDC_FLAT_LEVEL, m_wndFlatLevel);
	DDX_Control(pDX, IDC_ROTATE, m_wndRotate);
	DDX_Control(pDX, IDC_CHART, m_wndChart);
	DDX_Check(pDX, IDC_USE_SOFTWARE_RENDERING, m_bUseSoftwareRendering);
	DDX_CBIndex(pDX, IDC_SURFACE_TYPES, m_nSurfaceType);
	DDX_CBIndex(pDX, IDC_COLOR_MODE, m_nColorMode);
	DDX_CBIndex(pDX, IDC_COLOR_COUNT, m_nColorCount);
	DDX_Check(pDX, IDC_DRAW_FLAT, m_bDrawFlat);
	DDX_Slider(pDX, IDC_FLAT_LEVEL, m_nFlatLevel);
	DDX_CBIndex(pDX, IDC_FRAME_STYLE, m_nFrameStyle);
	DDX_Check(pDX, IDC_COLORED_FRAME, m_bColoredFrame);
	DDX_Check(pDX, IDC_LEGEND_LEVEL_RANGE, m_bShowLevelRangeInLegend);
	DDX_Check(pDX, IDC_CONT_LEGEND_KEY, m_bContinuousLegendKey);
	DDX_Check(pDX, IDC_SHOW_WALLS, m_bShowWalls);
	DDX_Check(pDX, IDC_WIRE_FRAME, m_bWireFrame);
	DDX_Check(pDX, IDC_ZOOM_SCROLL, m_bZoomScroll);
	DDX_Check(pDX, IDC_SHOW_FLOOR, m_bShowFloor);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CChartSurfaceAdvancedView, CBCGPChartExampleView)
	//{{AFX_MSG_MAP(CChartSurfaceAdvancedView)
	ON_BN_CLICKED(IDC_USE_SOFTWARE_RENDERING, OnUpdateChart)
	ON_BN_CLICKED(IDC_ROTATE, OnRotate)
	ON_WM_VSCROLL()
	ON_CBN_SELENDOK(IDC_SURFACE_TYPES, OnUpdateChart)
	ON_CBN_SELENDOK(IDC_COLOR_MODE, OnUpdateChart)
	ON_CBN_SELENDOK(IDC_COLOR_COUNT, OnUpdateChart)
	ON_CBN_SELENDOK(IDC_FRAME_STYLE, OnUpdateChart)
	ON_BN_CLICKED(IDC_DRAW_FLAT, OnUpdateChart)
	ON_BN_CLICKED(IDC_LEGEND_LEVEL_RANGE, OnUpdateChart)
	ON_BN_CLICKED(IDC_CONT_LEGEND_KEY, OnUpdateChart)
	ON_BN_CLICKED(IDC_COLORED_FRAME, OnUpdateChart)
	ON_BN_CLICKED(IDC_SHOW_WALLS, OnUpdateChart)
	ON_BN_CLICKED(IDC_SHOW_FLOOR, OnUpdateChart)
	ON_BN_CLICKED(IDC_ZOOM_SCROLL, OnUpdateChart)
	ON_BN_CLICKED(IDC_WIRE_FRAME, OnUpdateChart)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CChartSurfaceAdvancedView diagnostics

#ifdef _DEBUG
void CChartSurfaceAdvancedView::AssertValid() const
{
	CBCGPChartExampleView::AssertValid();
}

void CChartSurfaceAdvancedView::Dump(CDumpContext& dc) const
{
	CBCGPChartExampleView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CChartSurfaceAdvancedView message handlers

void CChartSurfaceAdvancedView::OnInitialUpdate() 
{
	CBCGPChartExampleView::OnInitialUpdate();
	
	if (m_bIsReady)
	{
		return;
	}

	m_bIsReady = TRUE;

	m_wndRotate.GetRotationObject()->SetAutorepeatMode(100);
	m_wndRotate.GetRotationObject()->SetColorTheme(CBCGPRotationObject::BCGP_COLOR_THEME_VISUAL_MANAGER);
	m_wndRotate.GetRotationObject()->EnableFlatIcons();

	m_wndFlatLevel.SetRange(0, 100, TRUE);

	CBCGPChartVisualObject* pChart = m_wndChart.GetChart();
	ASSERT_VALID(pChart);

	pChart->SetChartType(BCGPChartSurface3D);
	CBCGPChartSurfaceSeries* pSeries = DYNAMIC_DOWNCAST(CBCGPChartSurfaceSeries, pChart->CreateSeries(_T("Surface")));

	double dblStep = 0.15;
	double dblMinRange = -3;
	double dblMaxRange = 3.;

	for (double z = dblMinRange; z <= dblMaxRange + DBL_EPSILON; z += dblStep)
	{
		for (double x = dblMinRange; x <= dblMaxRange + DBL_EPSILON; x += dblStep)
		{
			double y = (cos(z * z) * z - sin(x * x) * x);
			pChart->AddChartDataYXZ(y, x, z);
		}
	}

	// calculate levels using minimum and maximum series values
	pSeries->SetLevelRangeMode(CBCGPChartSurfaceSeries::LRM_MINMAX_SERIES);

	// set up custom level colors
	pSeries->m_arCustomSurfaceColors.Add(CBCGPColor(CBCGPColor::LightPink));
	pSeries->m_arCustomSurfaceColors.Add(CBCGPColor(CBCGPColor::LightGreen));
	pSeries->m_arCustomSurfaceColors.Add(CBCGPColor(CBCGPColor::LightBlue));

	// set up axes
	CBCGPChartAxis* pXAxis = pChart->GetChartAxis(BCGP_CHART_X_PRIMARY_AXIS);
	CBCGPChartAxis* pZAxis = pChart->GetChartAxis(BCGP_CHART_Z_PRIMARY_AXIS);

	// center the chart by X and Z
	pXAxis->SetFixedDisplayRange(dblMinRange - 0.5, dblMaxRange + 0.5);
	pZAxis->SetFixedDisplayRange(dblMinRange - 0.5, dblMaxRange + 0.5);

	// turn off X and Z major grid lines
	pXAxis->ShowMajorGridLines(FALSE);
	pZAxis->ShowMajorGridLines(FALSE);

	// no interval interlacing on X axis
	pXAxis->EnableMajorUnitIntervalInterlacing(FALSE);

	// enable zoom and scroll
	pChart->SetZoomScrollConfig(BCGPChartMouseConfig::ZSO_WHEEL_PAN);

	OnUpdateChart();
}

void CChartSurfaceAdvancedView::OnUpdateChart() 
{
	UpdateData();

	CBCGPChartVisualObject* pChart = m_wndChart.GetChart();
	ASSERT_VALID(pChart);

	CBCGPChartDiagram3D* pDiagram3D = pChart->GetDiagram3D();
	ASSERT(pDiagram3D != NULL);

	pDiagram3D->SetRenderingType(
		m_bUseSoftwareRendering ? CBCGPEngine3D::BCGP_RT_SOFTWARE : CBCGPEngine3D::BCGP_RT_OPENGL);

	m_wndFlatLevel.EnableWindow(m_bDrawFlat);
	m_wndFlatLevelLabel.EnableWindow(m_bDrawFlat);

	m_wndColoredFrame.EnableWindow(m_nFrameStyle != 0);
	m_wndWireFrame.EnableWindow(m_nFrameStyle != 0);

	BOOL bNoFrame = (m_nFrameStyle == 0);

	for (int i = 0; i < pChart->GetSeriesCount(); i++)
	{
		CBCGPChartSurfaceSeries* pSeries = DYNAMIC_DOWNCAST(CBCGPChartSurfaceSeries, pChart->GetSeries(i));
		ASSERT_VALID(pSeries);

		pSeries->SetFrameStyle((CBCGPChartSurfaceSeries::FrameStyle)m_nFrameStyle);
		pSeries->SetWireFrame(m_bWireFrame && !bNoFrame);

		// set 4, 8, 12, 16 or 20 levels
		pSeries->SetColorMapCount((m_nColorCount + 1) * 4);
		pSeries->SetColorMode((CBCGPChartSurfaceSeries::ColorMode)m_nColorMode);

		// "Standard" or "Levels" surface types
		pSeries->SetSurfaceType((CBCGPChartSurfaceSeries::SurfaceType)m_nSurfaceType);

		pSeries->SetFrameStyle((CBCGPChartSurfaceSeries::FrameStyle)m_nFrameStyle);

		pSeries->SetFrameColor(
			m_bColoredFrame && !bNoFrame ?
			CBCGPBrush() :	// frame color is taken from level colors
			CBCGPBrush(CBCGPColor::LightGray));	// custom frame

		if (m_bDrawFlat)
		{
			CBCGPChartAxis* pYAxis = pSeries->GetRelatedAxis(CBCGPChartSeries::AI_Y);
			if (pYAxis != NULL)
			{
				double dblRange = pYAxis->GetMaxDisplayedValue() - pYAxis->GetMinDisplayedValue();

				// determine Y value of the "flat" surface, m_nFlatLevel is in range [0, 100] 
				double dblFlatValue = pYAxis->GetMinDisplayedValue() + dblRange * (100 - m_nFlatLevel) / 100.;
				pSeries->SetDrawFlat(TRUE, dblFlatValue);
			}
		}
		else
		{
			pSeries->SetDrawFlat(FALSE);
		}

		pSeries->EnableLevelRangeInLegendLabel(m_bShowLevelRangeInLegend);
		pSeries->SetContinuousLegendKey(m_bContinuousLegendKey);
	}

	if (m_nColorMode == 3)
	{
		// in "Custom" color mode set custom floor color
		pDiagram3D->m_formatWalls.m_brBottomFillColor.SetColor(CBCGPColor::LightBlue);
		pDiagram3D->m_formatWalls.m_brBottomFillColor.MakeLighter(0.2);

		// set wall and floor outline width
		pDiagram3D->m_formatWalls.m_outlineFormat.m_dblWidth = 2.;
	}
	else
	{
		// in other color modes restore the defaults
		pDiagram3D->m_formatWalls.m_brBottomFillColor.SetColor(CBCGPColor());
		pDiagram3D->m_formatWalls.m_outlineFormat.m_dblWidth = 1.;
	}

	// Show vertical axis:
	pChart->GetChartAxis(BCGP_CHART_Y_PRIMARY_AXIS)->m_bVisible = m_bShowWalls;

	DWORD dwoFlags = CBCGPChartDiagram3D::DWO_NONE;

	// Draw walls and floor:
	if (m_bShowWalls)
	{
		dwoFlags |= CBCGPChartDiagram3D::DWO_DRAW_ALL_WALLS;
	}

	if (m_bShowFloor)
	{
		dwoFlags |= CBCGPChartDiagram3D::DWO_DRAW_FLOOR;
	}
	else
	{
		// keep floor lines
		dwoFlags |= CBCGPChartDiagram3D::DWO_OUTLINE_FLOOR;
	}

	pDiagram3D->SetDrawWallOptions((CBCGPChartDiagram3D::DrawWallOptions)dwoFlags);

	// Zoom and scroll
	pChart->SetZoomScrollConfig(m_bZoomScroll ? BCGPChartMouseConfig::ZSO_WHEEL_PAN : BCGPChartMouseConfig::ZSO_NONE);

	m_wndRotate.GetRotationObject()->EnablePart(CBCGPRotationObject::BCGP_ROTATION_COUNTER_CLOCKWISE, m_bZoomScroll);
	m_wndRotate.GetRotationObject()->EnablePart(CBCGPRotationObject::BCGP_ROTATION_CLOCKWISE, m_bZoomScroll);
	m_wndRotate.GetRotationObject()->Redraw();

	if (!m_bZoomScroll)
	{
		pChart->UnZoom(FALSE);
	}

	pChart->SetDirty(TRUE, TRUE);
}

void CChartSurfaceAdvancedView::OnRotate() 
{
	CBCGPChartVisualObject* pChart = m_wndChart.GetChart();
	ASSERT_VALID(pChart);

	CBCGPChartDiagram3D* pDiagram3D = pChart->GetDiagram3D();
	ASSERT(pDiagram3D != NULL);

	double xDelta = 5.;
	double yDelta = 5.;
	double persperctiveDelta = 0.1;
	double dblZoomDelta = 0.1;

	double xRotation = pDiagram3D->GetXRotation();
	double yRotation = pDiagram3D->GetYRotation();

	double dblPerspectivePercent = pDiagram3D->GetPerspectivePercent();
	double dblZoomFactor = pDiagram3D->GetZoomFactor();

	switch (m_wndRotate.GetRotationObject()->GetClicked())
	{
	case CBCGPRotationObject::BCGP_ROTATION_UP:
		yRotation += yDelta;
		break;

	case CBCGPRotationObject::BCGP_ROTATION_DOWN:
		yRotation -= yDelta;
		break;

	case CBCGPRotationObject::BCGP_ROTATION_LEFT:
		xRotation -= xDelta;
		break;

	case CBCGPRotationObject::BCGP_ROTATION_RIGHT:
		xRotation += xDelta;
		break;

	case CBCGPRotationObject::BCGP_ROTATION_RESET:
		pDiagram3D->Reset(TRUE);
		pChart->UnZoom();
		dblZoomFactor = 1.;
		return;

	case CBCGPRotationObject::BCGP_ROTATION_NARROW_FIELD_OF_VIEW:
		dblPerspectivePercent -= persperctiveDelta;
		break;

	case CBCGPRotationObject::BCGP_ROTATION_WIDEN_FIELD_OF_VIEW:
		dblPerspectivePercent += persperctiveDelta;
		break;

	case CBCGPRotationObject::BCGP_ROTATION_COUNTER_CLOCKWISE:
		dblZoomFactor += dblZoomDelta;
		break;

	case CBCGPRotationObject::BCGP_ROTATION_CLOCKWISE:
		dblZoomFactor -= dblZoomDelta;
		break;
	}
	
	pDiagram3D->SetPosition(xRotation, yRotation, dblPerspectivePercent);
	pDiagram3D->SetZoomFactor(dblZoomFactor);

	pChart->SetDirty();
	pChart->Redraw();
}

void CChartSurfaceAdvancedView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	CBCGPChartExampleView::OnVScroll(nSBCode, nPos, pScrollBar);

	if (pScrollBar != NULL)
	{
		OnUpdateChart();
	}
}
